var AppalachianDB = {};

AppalachianDB.isInitialized = function() {
    var prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
    var init = false;
        if (prefs.prefHasUserValue("extensions.appalachian.initialized")) {
        init = prefs.getBoolPref("extensions.appalachian.initialized");
    } else {
        prefs.setBoolPref("extensions.appalachian.initialized", init);
    }
    return init;
};

AppalachianDB.error = function(e) {
    var bundle = document.getElementById("appalachian-db-bundle");
    var prefix = bundle.getString("sqlerror");
    alert(prefix + " " + e);
};

AppalachianDB.init = function() {
    var prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
    var prefix = "extensions.appalachian.";
    // check if initialized
    if (!AppalachianDB.isInitialized()) {
        // set some default pref values
            if (!prefs.prefHasUserValue(prefix + "defaultID")) {
            prefs.setIntPref(prefix + "defaultID", -1);
        }
            if (!prefs.prefHasUserValue(prefix + "useDefault")) {
            prefs.setBoolPref(prefix + "useDefault", true);
        }
            if (!prefs.prefHasUserValue(prefix + "showInStatusBar")) {
            prefs.setBoolPref(prefix + "showInStatusBar", true);
        }
        // get and run SQL from properties files
        var db = AppalachianDB.getHandle();
        var creationBundle = document.getElementById("creation-bundle");
        var createOpenIDSQL = creationBundle.getString("idcreation");
        var createServerSQL = creationBundle.getString("servercreation");
        var urlMapSQL = creationBundle.getString("usecreation");
        var dbBundle = document.getElementById("appalachian-db-bundle");
        var initFailure = dbBundle.getString("direfailure");
        try {
            db.executeSimpleSQL(createOpenIDSQL);
            db.executeSimpleSQL(createServerSQL);
            db.executeSimpleSQL(urlMapSQL);
            prefs.setBoolPref("extensions.appalachian.initialized", true);
        } catch (e) {
            alert(initFailure + " " + e);
            dump(e);
        }
    } else {
        // sigh; check if prefs exist
            if (!prefs.prefHasUserValue(prefix + "defaultID")) {
            prefs.setIntPref(prefix + "defaultID", -1);
        }
            if (!prefs.prefHasUserValue(prefix + "useDefault")) {
            prefs.setBoolPref(prefix + "useDefault", true);
        }
            if (!prefs.prefHasUserValue(prefix + "showInStatusBar")) {
            prefs.setBoolPref(prefix + "showInStatusBar", true);
        }
    }
};

AppalachianDB.getQuery = function(key) {
    var bundle = document.getElementById("appalachian-query-bundle");
    var sql = bundle.getString(key);
    return sql;
};

AppalachianDB.getFile = function() {
    var file = Components.classes["@mozilla.org/file/directory_service;1"]
            .getService(Components.interfaces.nsIProperties)
        .get("ProfD", Components.interfaces.nsIFile);
    file.append("appalachian.sqlite");
    return file;
};

AppalachianDB.getHandle = function() {
    var file = AppalachianDB.getFile();
    var storageService = Components.classes["@mozilla.org/storage/service;1"]
        .getService(Components.interfaces.mozIStorageService);
    var mDBConn = storageService.openDatabase(file);
    return mDBConn;
};

AppalachianDB.cosmeticListAll = function() {
    AppalachianDebug.trace("db.js", "> cosmeticListAll");
    var results = new Array();
    if (!AppalachianDB.isInitialized()) return results;
    var db = AppalachianDB.getHandle();
    var query = AppalachianDB.getQuery("cosmeticListAll");
    var st = db.createStatement(query);
    var info = null;
    try {
        while (st.executeStep()) {
            var id = st.getInt32(0);
            var url = st.getUTF8String(1);
            var use = st.getUTF8String(2);
            info = new OpenID(id, url, use);
            results.push(info);
        }
    } catch(e) {
        AppalachianDB.error(e);
    } finally {
        st.reset();
    }
    AppalachianDebug.trace("db.js", "< cosmeticListAll");
    return results;
};

AppalachianDB.listAll = function() {
    AppalachianDebug.trace("db.js", "> listAll");
    var results = new Array();
    if (!AppalachianDB.isInitialized()) return results;
    var db = AppalachianDB.getHandle();
    var query = AppalachianDB.getQuery("listAll");
    var st = db.createStatement(query);
    var oldid = -1;
    var servers = [];
    var info = null;
    try {
        while (st.executeStep()) {
            var id = st.getInt32(0);
            var url = st.getUTF8String(1);
            var use = st.getUTF8String(2);
            var server = st.getUTF8String(3);
            if (results.length == 0 && oldid == -1) {
                oldid = id;
                info = new OpenID(id, url, use, [server]);
            } else if (id != oldid) {
                results.push(info);
                oldid = id;
                info = new OpenID(id, url, use, [server]);
            } else {
                info.addServer(server);
            }
        }
        if (info != null) {
            results.push(info);
        }
    } catch(e) {
        AppalachianDB.error(e);
    } finally {
        st.reset();
    }
    AppalachianDebug.trace("db.js", "< listAll");
    return results;
};

AppalachianDB.countServers = function(id) {
    var result;
    var db = AppalachianDB.getHandle();
    var query = AppalachianDB.getQuery("countServers");
    var st = db.createStatement(query);
    try {
        st.bindInt32Parameter(0, id);
        st.executeStep();
        result = st.getInt32(0);
    } catch(e) {
        AppalachianDB.error(e);
    } finally {
        st.reset();
    }
    return result;
};

AppalachianDB.listServers = function(openid) {
    var results = new Array();
    var db = AppalachianDB.getHandle();
    var query = AppalachianDB.getQuery("listServers");
    var st = db.createStatement(query);
    try {
        st.bindInt32Parameter(0, openid);
        while (st.executeStep()) {
            var id = st.getInt32(0);
            var server = st.getUTF8String(1);
            var server = { "id" : id, "server" : server };
            results.push(server);
        }
    } catch(e) {
        AppalachianDB.error(e);
    } finally {
        st.reset();
    }
    return results;
};

AppalachianDB.listUses = function(id) {
    var results = new Array();
    var db = AppalachianDB.getHandle();
    var query = AppalachianDB.getQuery("listUses");
    var st = db.createStatement(query);
    try {
        st.bindInt32Parameter(0, id);
        while (st.executeStep()) {
            var useid = st.getInt32(0);
            var url = st.getUTF8String(1);
            var field = st.getInt32(2);
            var form = st.getInt32(3);
            var use = { "id" : useid, "url" : url, "field" : field, "form" : form };
            results.push(use);
        }
    } catch(e) {
        AppalachianDB.error(e);
    } finally {
        st.reset();
    }
    return results;
};

AppalachianDB.getUse = function(useid, openid) {
    var result;
    var db = AppalachianDB.getHandle();
    var query = AppalachianDB.getQuery("getUse");
    var st = db.createStatement(query);
    try {
        st.bindInt32Parameter(0, useid);
        st.bindInt32Parameter(1, openid);
        st.executeStep();
        var field = st.getInt32(2);
        var form = st.getInt32(3);
        result = { "use_id" : useid, "openid" : openid, "field" : field, "form" : form };
    } catch(e) {
        AppalachianDB.error("getUse:" + e);
    } finally {
        st.reset();
    }
    return result;
};

AppalachianDB.anyUseExists = function(url) {
    var result = false;
    var db = AppalachianDB.getHandle();
    var query = AppalachianDB.getQuery("anyUseExists");
    var st = db.createStatement(query);
    try {
        st.bindUTF8StringParameter(0, AppalachianDB.normalizeUrl(url));
        while (st.executeStep()) {
            var count = st.getInt32(0);
            result = count > 0;
        }
    } catch(e) {
        AppalachianDB.error(e);
    } finally {
        st.reset();
    }
    return result;
}

AppalachianDB.listUsesIds = function(url) {
    var results = new Array();
    var db = AppalachianDB.getHandle();
    var query = AppalachianDB.getQuery("listUsesIds");
    var st = db.createStatement(query);
    try {
        st.bindUTF8StringParameter(0, url);
        while (st.executeStep()) {
            var id = st.getInt32(0);
            var openid = st.getInt32(1);
            var field = st.getInt32(2);
            var form = st.getInt32(3);
            var id_use = { "use_id" : id, "openid" : openid, "field" : field, "form" : form };
            results.push(id_use);
        }
    } catch(e) {
        AppalachianDB.error(e);
    } finally {
        st.reset();
    }
    return results;
};

AppalachianDB.getInfo = function(id) {
    var info;
    var db = AppalachianDB.getHandle();
    var query = AppalachianDB.getQuery("getInfo");
    var st = db.createStatement(query);
    try {
        st.bindInt32Parameter(0, id);
        var servers = [];
        while (st.executeStep()) {
            var url = st.getUTF8String(0);
            var use = st.getUTF8String(1);
            var server = st.getUTF8String(2);
            servers.push(server);
        }
        info = new OpenID(id, url, use, servers);
    } catch (e) {
        AppalachianDB.error(e);
    } finally {
        st.reset();
    }
    return info;
};

AppalachianDB.getServerInfo = function(id) {
    var info;
    var db = AppalachianDB.getHandle();
    var query = AppalachianDB.getQuery("getServerInfo");
    var st = db.createStatement(query);
    try {
        st.bindInt32Parameter(0, id);
        st.executeStep();
        var server = st.getUTF8String(0);
        info = { url : server };
    } catch (e) {
        AppalachianDB.error(e);
    } finally {
        st.reset();
    }
    return info;
};

AppalachianDB.getInfoByUrl = function(url) {
    var out;
    var db = AppalachianDB.getHandle();
    var query = AppalachianDB.getQuery("idrow");
    var st = db.createStatement(query);
    try {
        st.bindUTF8StringParameter(0, url);
        st.executeStep();
        out = st.getInt32(0);
    } catch (e) {
        AppalachianDB.error(e);
    } finally {
        st.reset();
    }
    return out;
};

AppalachianDB.exists = function(url) {
    var out = false;
    var db = AppalachianDB.getHandle();
    var query = AppalachianDB.getQuery("idExists"); 
    var st = db.createStatement(query);
    try {
        st.bindUTF8StringParameter(0, url);
        st.executeStep();
        var count = st.getInt32(0);
        out = count > 0;
    } catch (e) {
        AppalachianDB.error(e);
    } finally {
        st.reset();
    }
    return out;
};

AppalachianDB.add = function(url, use, servers, cont) {
    AppalachianDebug.trace("db.js", "> add " + url + " " + use + " " + servers);
    var dbBundle = document.getElementById("appalachian-db-bundle");
    var failmsg = dbBundle.getString("existserror");
    if (AppalachianDB.exists(url)) throw (failmsg);
    var id;
    var db = AppalachianDB.getHandle();
    var query = AppalachianDB.getQuery("addOpenid");
    var st = db.createStatement(query);
    try {
        st.bindUTF8StringParameter(0, url);
        st.bindUTF8StringParameter(1, use);
        st.execute();
    } catch (e) {
        AppalachianDB.error(e);
    }

    query = AppalachianDB.getQuery("idrow");
    st = db.createStatement(query);
    try {
        st.bindUTF8StringParameter(0, url);
        st.executeStep();
        id = st.getInt32(0);
    } catch (e) {
        AppalachianDB.error(e);
    }

    for (var i = 0; i < servers.length; i++) {
        query = AppalachianDB.getQuery("addServer");
        st = db.createStatement(query);
        try {
            st.bindInt32Parameter(0, id);
            st.bindUTF8StringParameter(1, servers[i]);
            st.execute();
        } catch (e) {
            AppalachianDB.error(e);
        }
    }
    
    AppalachianDebug.trace("db.js", "< add");
    if (cont) {
        cont(id);
    } else {
        return id;
    }
};

AppalachianDB.serverExists = function(openid, server) {
    var out = false;
    var db = AppalachianDB.getHandle();
    var query = AppalachianDB.getQuery("serverExists"); 
    var st = db.createStatement(query);
    try {
        st.bindInt32Parameter(0, openid);
        st.bindUTF8StringParameter(1, server);
        st.executeStep();
        var count = st.getInt32(0);
        out = count > 0;
    } catch (e) {
        AppalachianDB.error(e);
    } finally {
        st.reset();
    }
    return out;
};

AppalachianDB.addServer = function(openid, server) {
    var dbBundle = document.getElementById("appalachian-db-bundle");
    var failmsg = dbBundle.getString("serverexistserror");
    if (AppalachianDB.serverExists(openid, server)) throw (failmsg);
    var id;
    var db = AppalachianDB.getHandle();
    var query = AppalachianDB.getQuery("addServer");
    var st = db.createStatement(query);
    try {
        st.bindInt32Parameter(0, openid);
        st.bindUTF8StringParameter(1, server);
        st.execute();
    } catch (e) {
        AppalachianDB.error(e);
    }
};

AppalachianDB.useExists = function(openid ,url) {
    var out = false;
    var db = AppalachianDB.getHandle();
    var query = AppalachianDB.getQuery("useExists");    
    var st = db.createStatement(query);
    try {
        st.bindInt32Parameter(0, openid);
        st.bindUTF8StringParameter(1, url);
        st.executeStep();
        var count = st.getInt32(0);
        out = count > 0;
    } catch (e) {
        AppalachianDB.error(e);
    } finally {
        st.reset();
    }
    return out;
};

AppalachianDB.getUseId = function(openid, url) {
    var out;
    var db = AppalachianDB.getHandle();
    var query = AppalachianDB.getQuery("getUseId");
    var st = db.createStatement(query);
    try {
        st.bindInt32Parameter(0, openid);
        st.bindUTF8StringParameter(1, url);
        st.executeStep();
        var out = st.getInt32(0);
    } catch (e) {
        AppalachianDB.error(e);
    } finally {
        st.reset();
    }
    return out;
};

AppalachianDB.normalizeUrl = function(url) {
    // remove # frags, or anything else necessary when dealing with
    // internal URLs; currently for recorded sites *only*
    var normal = url;
    if (url.indexOf('#') > 0) {
        normal = url.substring(0, url.indexOf('#'));
    }
    return normal;
}

AppalachianDB.recordUse = function(openid, url, field, form) {
    url = AppalachianDB.normalizeUrl(url);
    if (AppalachianDB.useExists(openid, url)) return;
    var db = AppalachianDB.getHandle();
    var query = AppalachianDB.getQuery("recordUse");
    var st = db.createStatement(query);
    try {
        st.bindInt32Parameter(0, openid);
        st.bindUTF8StringParameter(1, url);
        st.bindInt32Parameter(2, field);
        st.bindInt32Parameter(3, form);
        st.execute();
    } catch (e) {
        AppalachianDB.error(e);
    }
};

AppalachianDB.modify = function(id, url, use) {
    var dbBundle = document.getElementById("appalachian-db-bundle");
    var failmsg = dbBundle.getString("existserror");
    if (AppalachianDB.exists(url)) throw (failmsg);
    var db = AppalachianDB.getHandle();
    var query = AppalachianDB.getQuery("modifyOpenid");
    var st = db.createStatement(query);
    try {
        st.bindUTF8StringParameter(0, url);
        st.bindUTF8StringParameter(1, use);
        st.bindInt32Parameter(2, id);
        st.execute();
    } catch (e) {
        AppalachianDB.error(e);
    }
};

AppalachianDB.modifyServer = function(id, openid, server) {
    var dbBundle = document.getElementById("appalachian-db-bundle");
    var failmsg = dbBundle.getString("serverexistserror");
    if (AppalachianDB.serverExists(openid, server)) throw (failmsg);
    var db = AppalachianDB.getHandle();
    var query = AppalachianDB.getQuery("modifyServer");
    var st = db.createStatement(query);
    try {
        st.bindUTF8StringParameter(0, server);
        st.bindInt32Parameter(1, id);
        st.execute();
    } catch (e) {
        AppalachianDB.error(e);
    }
};

AppalachianDB.deleteServer = function(id) {
    var db = AppalachianDB.getHandle();
    var query = AppalachianDB.getQuery("deleteServerById");
    var st = db.createStatement(query);
    try {
        st.bindInt32Parameter(0, id);
        st.execute();
    } catch (e) {
        AppalachianDB.error(e);
    }
};

AppalachianDB.delete = function(id) {
    var db = AppalachianDB.getHandle();
    var query = AppalachianDB.getQuery("deleteServerByOpenid");
    var st = db.createStatement(query);
    try {
        st.bindInt32Parameter(0, id);
        st.execute();
    } catch (e) {
        AppalachianDB.error(e);
    }

    query = AppalachianDB.getQuery("delete");
    st = db.createStatement(query);
    try {
        st.bindInt32Parameter(0, id);
        st.execute();
    } catch (e) {
        AppalachianDB.error(e);
    }
};

AppalachianDB.deleteUse = function(useid) {
    var db = AppalachianDB.getHandle();
    var query = AppalachianDB.getQuery("deleteUse");
    var st = db.createStatement(query);
    try {
        st.bindInt32Parameter(0, useid);
        st.execute();
    } catch (e) {
        AppalachianDB.error(e);
    }
};

// completely destroy the entire database
AppalachianDB.wipe = function() {
    var file = AppalachianDB.getFile();
    file.remove(false);
    var prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
    prefs.clearUserPref("extensions.appalachian.initialized");
    prefs.clearUserPref("extensions.appalachian.defaultID");
};
